package 设计模式.工厂方法模式;

/**
 * @description: 引入设计模式的意义：在变化(抽象部分)的代码中寻找不变(稳定部分)的代码，设计成一个模式
 * 工厂方法模式的本质：把类的实例化过程推迟到子类(工厂根据需求即参数等等，实例化不同的类）
 * (需要继承一个统一父类，这个父类是抽象父类，抽象方法是不变的，子类需要自定义该抽象方法的内容）
 * 特点：
 * 将具体产品和创建者解耦
 * 符合开闭原则：扩张和开放，需要其他product直接继承抽象父类
 * 符合单一指着原则：每个product的方法内容都是自己独有的，与其他product互不干扰。
 *
 * 简单工厂模式：通过不通的参数来实例化不同的对象
 * Spring中的beanFactory则利用不通的BeanName来实例化不同的单例或者获取
 * 区别：简单工厂模式只需要传入对应参数获取对应实例
 *      工厂方法模式，需要自己实例化（new）对应的实例
 * @author: Kk
 * @create: 2020-12-08 08:58
 **/
public class FactoryMethod {
    public static void main(String[] args) {

        Product product1 = SimpleFactory.createProduct("1");
        product1.method1();

        ApplicationContext applicationContext =new ConcreteProductA1();
        Product product = applicationContext.createProduct();
        product.method1();
    }
}

//简单工厂 类似spring的beanFactory,传入beanName，beanFactory就会给出相应的单例
class SimpleFactory{
    public static Product createProduct(String beanName){
        if (beanName.equals("0")){
            return new ProductA();
        }else if (beanName.equals("1")){
            return new ProductA1();
        }else {
            return null;
        }
    }
}

interface Product{
    public void method1();
}

class ProductA implements Product {
    @Override
    public void method1(){
        System.out.println("ProductA.method1 executed...");
    }
}
class ProductA1 implements Product {
    @Override
    public void method1(){
        System.out.println("ProductA1.method1 executed...");
    }
}

abstract class ApplicationContext {
    //工厂方法：不变的稳定因素，变化的是继承的子类中自己实现部分。
    abstract Product createProduct();
    /*Product getBean(){
        Product product = createProduct();
        //多例
        //...
        return product;
    }*/
}

class ConcreteProductA extends ApplicationContext {
    @Override
    Product createProduct() {
        return new ProductA();
    }
}
class ConcreteProductA1 extends ApplicationContext {
    @Override
    Product createProduct() {
        return new ProductA1();
    }
}
